#include "include/Character.h"
#include "include/GlobalGameObj.h"
#include "include/Utils.h"

#include <stdlib.h>
#include <boost/lexical_cast.hpp>
#include <vector>

using namespace boost;

void Character::CreateBasicSqlStr(BasicInfo *p_info, string &sql_str)
{
	sql_str = "(character_id,player_id,name,gang_name,rank,gender,level,job,title,"
		"reward,exp,max_exp,reputation,"
		"hp,kongfu,specialty,theurgy,res_id,"
		"equip_pos_str,equip_id_str,ch_equip_id_str,"
		"skill_id_str,formation_str,"
		"pet_id_str,pet_name_str,pet_level_str,"
		"online,scene_id,speed,last_online_time) values('" +
		lexical_cast<string>(p_info->character_id) + "','" +
		lexical_cast<string>(p_info->player_id) + "','" +
		p_info->name + "','" +
		p_info->gang_name + "','" +
		lexical_cast<string>(p_info->rank) + "','" +
		lexical_cast<string>(p_info->gender) + "','" +
		lexical_cast<string>(p_info->level) + "','" +
		lexical_cast<string>(p_info->job) + "','" +
		p_info->title + "','" +
		lexical_cast<string>(p_info->reward) + "','" +
		lexical_cast<string>(p_info->exp) + "','" +
		lexical_cast<string>(p_info->max_exp) + "','" +
		lexical_cast<string>(p_info->reputation) + "','" +
		lexical_cast<string>(p_info->hp) + "','" +
		lexical_cast<string>(p_info->kongfu) + "','" +
		lexical_cast<string>(p_info->specialty) + "','" +
		lexical_cast<string>(p_info->theurgy) + "','" +
		lexical_cast<string>(p_info->res_id) + "','" +
		p_info->equip_pos_str + "','" +
		p_info->equip_id_str + "','" +
		p_info->ch_equip_id_str + "','" +
		p_info->skill_id_str + "','" +
		p_info->formation_str + "','" +
        p_info->pet_id_str + "','" +
		p_info->pet_name_str + "','" +
		p_info->pet_level_str + "','" +
		lexical_cast<string>(p_info->online) + "','" +
		p_info->scene_id + "','" +
		lexical_cast<string>(p_info->speed) + "','" +
		p_info->last_online_time + "');";
}

void Character::CreateDetailSqlStr(DetailInfo *p_info, string &sql_str)
{
	sql_str = "(character_id,name,job,skill_id_str,head_id,level,hp,"
        "attack,defence,specialty_attack,specialty_defence,theurgy_attack,theurgy_defence,"
        "critical,thoughness,hit,dodge,destory,parry,angry,prior_attack) values(" +
		lexical_cast<string>(p_info->character_id) + "','" +
		p_info->name + "','" +
		lexical_cast<string>(p_info->job) + "','" +
		p_info->skill_id_str + "','" +
		lexical_cast<string>(p_info->head_id) + "','" +
		lexical_cast<string>(p_info->level) + "','" +
		lexical_cast<string>(p_info->hp) + "','" +
		lexical_cast<string>(p_info->attack) + "','" +
		lexical_cast<string>(p_info->defence) + "','" +
		lexical_cast<string>(p_info->specialty_attack) + "','" +
		lexical_cast<string>(p_info->specialty_defence) + "','" +
		lexical_cast<string>(p_info->theurgy_attack) + "','" +
		lexical_cast<string>(p_info->theurgy_defence) + "','" +
		lexical_cast<string>(p_info->critical) + "','" +
		lexical_cast<string>(p_info->toughness) + "','" +
		lexical_cast<string>(p_info->hit) + "','" +
		lexical_cast<string>(p_info->dodge) + "','" +
		lexical_cast<string>(p_info->destroy) + "','" +
		lexical_cast<string>(p_info->parry) + "','" +
		lexical_cast<string>(p_info->angry) + "','" +
		lexical_cast<string>(p_info->prior_attack) + ")";
}

void Character::GetBasicInfo(GlobalGameObj *p_game_obj, int character_id, BasicInfo *p_info)
{
	string value;

	if(p_game_obj->model_proxy.GetObjectById(
		"tbl_character", "character_id", character_id, value))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "Character::GetBasicInfo";

		return;
	}

	vector<string> strList;
	Utils::Str2StrList(value, strList, '|');

#ifdef _DEBUG_LEVEL_1_
	cout << "after Str2StrList in GetBasicInfo" << endl;
#endif

	int i = 0;

	p_info->character_id = atoi(strList[i++].c_str());
	p_info->player_id = atoi(strList[i++].c_str());
	p_info->name = strList[i++].c_str();
	p_info->gang_name = strList[i++].c_str();
	p_info->rank = atoi(strList[i++].c_str());
	p_info->gender = atoi(strList[i++].c_str());
	p_info->level = atoi(strList[i++].c_str());
	p_info->job = atoi(strList[i++].c_str());
	p_info->title = strList[i++].c_str();
	p_info->reward = atoi(strList[i++].c_str());
	p_info->exp = atoi(strList[i++].c_str());
	p_info->max_exp = atoi(strList[i++].c_str());
	p_info->reputation = atoi(strList[i++].c_str());
	p_info->hp = atoi(strList[i++].c_str());
	p_info->kongfu = atoi(strList[i++].c_str());
	p_info->specialty = atoi(strList[i++].c_str());
	p_info->theurgy = atoi(strList[i++].c_str());
	p_info->res_id = atoi(strList[i++].c_str());
	p_info->equip_pos_str = strList[i++].c_str();
	p_info->equip_id_str = strList[i++].c_str();
	p_info->ch_equip_id_str = strList[i++].c_str();
	p_info->skill_id_str = strList[i++].c_str();
	p_info->formation_str = strList[i++].c_str();
	p_info->pet_id_str = strList[i++].c_str();
	p_info->pet_name_str = strList[i++].c_str();
	p_info->pet_level_str = strList[i++].c_str();
	p_info->online = atoi(strList[i++].c_str());
	p_info->scene_id = strList[i++].c_str();
	p_info->speed = atoi(strList[i++].c_str());
	p_info->last_online_time = strList[i++].c_str();
}

void Character::GetBasicInfoTree(GlobalGameObj *p_game_obj, int character_id, ptree &info_tree)
{
    BasicInfo basic_info;
    GetBasicInfo(p_game_obj, character_id, &basic_info);
    if(Common::NoError != p_game_obj->error_code)
    {
        return;
    }

    info_tree.put("characterId", basic_info.character_id);
	info_tree.put("name", basic_info.name);
	info_tree.put("gangName", basic_info.gang_name);
	info_tree.put("rank", basic_info.rank);
	info_tree.put("gender", basic_info.gender);
	info_tree.put("level", basic_info.level);
	info_tree.put("job", basic_info.job);
	info_tree.put("title", basic_info.title);
	info_tree.put("reward", basic_info.reward);
	info_tree.put("exp", basic_info.exp);
	info_tree.put("maxExp", basic_info.max_exp);
	info_tree.put("reputation", basic_info.reputation);
	info_tree.put("skillIdStr", basic_info.skill_id_str);
	info_tree.put("formationStr", basic_info.formation_str);

	ptree attrib_tree;
	attrib_tree.put("hp", basic_info.hp);
	attrib_tree.put("kongfu", basic_info.kongfu);
	attrib_tree.put("specialty", basic_info.specialty);
	attrib_tree.put("theurgy", basic_info.theurgy);
	info_tree.put_child("baseAttrib", attrib_tree);

    info_tree.put("resId", basic_info.res_id);

	ptree equip_tree;
	vector<string> equip_id_list;
	vector<string> ch_equip_id_list;
	vector<string> equip_pos_list;
	Utils::Str2StrList(basic_info.equip_id_str, equip_id_list, '^');
	Utils::Str2StrList(basic_info.ch_equip_id_str, ch_equip_id_list, '^');
	Utils::Str2StrList(basic_info.equip_pos_str, equip_pos_list, '^');

	if(equip_id_list.size() != ch_equip_id_list.size() ||
			equip_id_list.size() != equip_pos_list.size())
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = " Character::GetBasicInfoTree: "
			" equip_id_list, ch_equip_id_list, equip_pos_list error: " +
			basic_info.equip_id_str + "," + basic_info.ch_equip_id_str + "," +
			basic_info.equip_pos_str;

		cout << __FUNCTION__ << " equip_id_list, ch_equip_id_list, equip_pos_list error: " <<
			basic_info.equip_id_str << "," << basic_info.ch_equip_id_str << "," <<
			basic_info.equip_pos_str << endl;

		return;
	}

#ifdef _DEBUG_LEVEL_1_
	cout << __FUNCTION__ << " step 4" << endl;
	cout << "equip_id_list size: " << equip_id_list.size() << endl;
	cout << "ch_equip_id_list size: " << ch_equip_id_list.size() << endl;
	cout << "equip_pos_list size: " << equip_pos_list.size() << endl;
	cout << "ch_equip_id_list: " << basic_info.ch_equip_id_str << endl;
#endif

	for(unsigned int i = 0; i < equip_id_list.size(); i++)
	{
		ptree item_tree;

		item_tree.put("pos", atoi(equip_pos_list[i].c_str()));
		item_tree.put("equipId", atoi(equip_id_list[i].c_str()));
		item_tree.put("chEquipId", atoi(ch_equip_id_list[i].c_str()));

		equip_tree.push_back(make_pair("", item_tree));
	}

#ifdef _DEBUG_LEVEL_1_
	cout << __FUNCTION__ << " step 5" << endl;
#endif
	info_tree.put_child("equip", equip_tree);

	ptree pet_tree;
	vector<string> pet_id_list;
	vector<string> pet_name_list;
	vector<string> pet_level_list;
	Utils::Str2StrList(basic_info.pet_id_str, pet_id_list, '^');
	Utils::Str2StrList(basic_info.pet_name_str, pet_name_list, '^');
	Utils::Str2StrList(basic_info.pet_level_str, pet_level_list, '^');

	if(pet_id_list.size() != pet_name_list.size() ||
			pet_id_list.size() != pet_level_list.size())
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = " Character::GetBasicInfoTree: "
			" pet_id_list, pet_name_list, pet_level_list error: " +
			basic_info.pet_id_str + "," + basic_info.pet_name_str + "," +
			basic_info.pet_level_str;

		cout << __FUNCTION__ << " pet_id_list, pet_name_list, pet_level_list error: " <<
			basic_info.pet_id_str << "," << basic_info.pet_name_str << "," <<
			basic_info.pet_level_str << endl;

		return;
	}

#ifdef _DEBUG_LEVEL_1_
	cout << __FUNCTION__ << " step 4" << endl;
	cout << "pet_id_list size: " << pet_id_list.size() << endl;
	cout << "pet_name_list size: " << pet_name_list.size() << endl;
	cout << "pet_level_list size: " << pet_level_list.size() << endl;
#endif

	try
	{
	    cout << "1111" << endl;
		for(unsigned int i = 0; i < pet_id_list.size(); i++)
		{
			ptree item_tree;

			item_tree.put("petId", atoi(pet_id_list[i].c_str()));
			item_tree.put("name", atoi(pet_name_list[i].c_str()));
			item_tree.put("level", atoi(pet_level_list[i].c_str()));

			pet_tree.push_back(make_pair("", item_tree));
		}
		cout << "2222" << endl;
		info_tree.put_child("pet", pet_tree);

        cout << "3333" << endl;
		info_tree.put("online", basic_info.online);
		info_tree.put("sceneId", basic_info.scene_id);
		info_tree.put("speed", basic_info.speed);
		info_tree.put("last_online_time", basic_info.last_online_time);

		cout << "4444" << endl;
	}
	catch(boost::exception &ex)
	{
		p_game_obj->error_code = Common::JsonTreeError;
		p_game_obj->error_str = "put info tree error in get basic info";

#ifdef _DEBUG_LEVEL_1_
		cout << "error in put info tree in get basic info" << endl;
#endif
	}

#ifdef _DEBUG_LEVEL_1_
	cout << "end of get basic info tree" << endl;
#endif
}

void Character::GetDetailInfo(GlobalGameObj *p_game_obj, int character_id, DetailInfo *p_info)
{
	string value;

	if(p_game_obj->model_proxy.GetObjectById(
		"tbl_character_detail", "character_id", character_id, value))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = " Character::GetDetailInfo";

		return;
	}

	vector<string> strList;

	Utils::Str2StrList(value, strList, '|');

	int i = 0;

	p_info->character_id = atoi(strList[i++].c_str());
	p_info->name = strList[i++].c_str();
	p_info->job = atoi(strList[i++].c_str());
	p_info->skill_id_str = strList[i++].c_str();
	p_info->head_id = atoi(strList[i++].c_str());
	p_info->level = atoi(strList[i++].c_str());
	p_info->hp = atoi(strList[i++].c_str());
	p_info->attack = atoi(strList[i++].c_str());
	p_info->defence = atoi(strList[i++].c_str());
	p_info->specialty_attack= atoi(strList[i++].c_str());
	p_info->specialty_defence = atoi(strList[i++].c_str());
	p_info->theurgy_attack = atoi(strList[i++].c_str());
	p_info->theurgy_defence = atoi(strList[i++].c_str());
	p_info->critical = atoi(strList[i++].c_str());
	p_info->toughness = atoi(strList[i++].c_str());
	p_info->hit = atoi(strList[i++].c_str());
	p_info->dodge = atoi(strList[i++].c_str());
	p_info->destroy = atoi(strList[i++].c_str());
	p_info->parry = atoi(strList[i++].c_str());
	p_info->angry = atoi(strList[i++].c_str());
	p_info->prior_attack = atoi(strList[i++].c_str());
}

void Character::GetDetailInfoTree(GlobalGameObj *p_game_obj, int character_id, ptree &info_tree)
{
    DetailInfo detail_info;
    GetDetailInfo(p_game_obj, character_id, &detail_info);
    if(Common::NoError != p_game_obj->error_code)
    {
        return;
    }

    info_tree.put("characterId", detail_info.character_id);
	info_tree.put("name", detail_info.name);
	info_tree.put("job", detail_info.job);
	info_tree.put("skillIdStr", detail_info.skill_id_str);
	info_tree.put("level", detail_info.level);
	info_tree.put("headId", detail_info.head_id);
	info_tree.put("hp", detail_info.hp);
	info_tree.put("attack", detail_info.attack);
	info_tree.put("defence", detail_info.defence);
	info_tree.put("specialtyAttack", detail_info.specialty_attack);
	info_tree.put("specialtyDefence", detail_info.specialty_defence);
	info_tree.put("theurgyAttack", detail_info.theurgy_attack);
	info_tree.put("theurgyDefence", detail_info.theurgy_defence);
	info_tree.put("critical", detail_info.critical);
	info_tree.put("toughness", detail_info.toughness);
	info_tree.put("hit", detail_info.hit);
	info_tree.put("dodge", detail_info.dodge);
	info_tree.put("destroy", detail_info.destroy);
	info_tree.put("parry", detail_info.parry);
	info_tree.put("angry", detail_info.angry);
	info_tree.put("priorAttack", detail_info.prior_attack);
}

void Character::UpdateBasicInfo(GlobalGameObj *p_game_obj, BasicInfo *p_info)
{
	string sql_str;
	CreateBasicSqlStr(p_info, sql_str);
	if(p_game_obj->model_proxy.ReplaceObjectById("tbl_character", "character_id",
        p_info->character_id, sql_str))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "UpdateBasicInfo, ReplaceObject error";
	}
}

void Character::UpdateDetailInfo(GlobalGameObj *p_game_obj, DetailInfo *p_info)
{
	string sql_str;
	CreateDetailSqlStr(p_info, sql_str);
	if(p_game_obj->model_proxy.ReplaceObjectById("tbl_character", "character_id",
        p_info->character_id, sql_str))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "UpdateDetailInfo, ReplaceObject error";
	}
}

void Character::CreateBasicInfo(GlobalGameObj *p_game_obj, BasicInfo *p_info)
{
	string sql_str;
	CreateBasicSqlStr(p_info, sql_str);
	if(p_game_obj->model_proxy.InsertObject("tbl_character", sql_str))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "CreateBasicInfo, InsertObject error";
	}
}

void Character::CreateDetailInfo(GlobalGameObj *p_game_obj, DetailInfo *p_info)
{
	string sql_str;
	CreateDetailSqlStr(p_info, sql_str);
	if(p_game_obj->model_proxy.InsertObject("tbl_character_detail", sql_str))
	{
		p_game_obj->error_code = Common::ModelError;
		p_game_obj->error_str = "CreateDetailInfo, InsertObject error";
	}
}

